package com.sjr.easy.chat.app.mq;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.sjr.easy.chat.app.constants.RabbitMQConstants;
import com.sjr.easy.chat.app.utils.RabbitMessageUtils;
import com.sjr.easy.chat.app.utils.SequenceUtils;
import com.sjr.easy.chat.app.ws.AppWSMessage;
import com.sjr.easy.chat.app.ws.AppWSMessageTypeEnum;
import com.sjr.easy.chat.app.ws.WSConnectionManager;
import com.sjr.easy.chat.model.ChatGroupUser;
import com.sjr.easy.chat.model.Conversation;
import com.sjr.easy.chat.model.InboxMessage;
import com.sjr.easy.chat.model.OutboxMessage;
import com.sjr.easy.chat.service.ChatGroupUserService;
import com.sjr.easy.chat.service.ConversationService;
import com.sjr.easy.chat.service.OutboxMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Component
public class NewInboxMessageMessageListener {

    @Autowired
    private OutboxMessageService outboxMessageService;

    @Autowired
    private SequenceUtils sequenceUtils;

    @Autowired
    private WSConnectionManager wsConnectionManager;

    @Autowired
    private ConversationService conversationService;

    @Autowired
    private ChatGroupUserService chatGroupUserService;

    @RabbitListener(
            bindings = @QueueBinding(
                    value = @Queue(RabbitMQConstants.NewInboxMessageDeliverQueue),
                    exchange = @Exchange(
                            name = RabbitMQConstants.NewInboxMessageExchange,
                            type = ExchangeTypes.FANOUT
                    )
            )
    )
    public void newInboxMessageMessageListenerDeliver(Message message) {
        InboxMessage inboxMessage = RabbitMessageUtils.messageBodyAsObject(message, InboxMessage.class);
        log.info("inboxMessage:{}", inboxMessage);

        Conversation conversation = conversationService.getConversation(
                inboxMessage.getSourceUserId(), inboxMessage.getTargetUserId(), inboxMessage.getChatGroupId());

        if (Objects.equals(conversation.getType(), 1)) {
            generalMsgDeliver(inboxMessage);
        }
        if (Objects.equals(conversation.getType(), 2)) {
            chatGroupMsgDeliver(inboxMessage);
        }
    }


    private void generalMsgDeliver(InboxMessage inboxMessage) {
        OutboxMessage outboxMessage = new OutboxMessage();

        outboxMessage.setId(sequenceUtils.genOutboxMessageId());
        outboxMessage.setInboxMessageId(inboxMessage.getId());
        outboxMessage.setConversationId(inboxMessage.getConversationId());
        outboxMessage.setSourceUserId(inboxMessage.getSourceUserId());
        outboxMessage.setTargetUserId(inboxMessage.getTargetUserId());
        outboxMessage.setMessageType(inboxMessage.getMessageType());
        outboxMessage.setMessage(inboxMessage.getMessage());
        outboxMessage.setStatus(0);
        outboxMessage.setCreateTime(new Date());
        outboxMessage.setSendTime(inboxMessage.getSendTime());

        outboxMessageService.addOutboxMessage(outboxMessage);

        AppWSMessage appWSMessage = new AppWSMessage();
        appWSMessage.setType(AppWSMessageTypeEnum.NEW_MSG.getTypeName());
        wsConnectionManager.sendMessage(outboxMessage.getTargetUserId(), new TextMessage(JSON.toJSONString(appWSMessage)));
    }

    private void chatGroupMsgDeliver(InboxMessage inboxMessage) {
        List<ChatGroupUser> chatGroupUserList = chatGroupUserService.selectByChatGroupId(inboxMessage.getChatGroupId());

        List<Long> targetUserIdList = new ArrayList<>();
        List<OutboxMessage> outboxMessageList = Lists.newArrayList();
        for (ChatGroupUser chatGroupUser : chatGroupUserList) {
            if (Objects.equals(chatGroupUser.getUserId(), inboxMessage.getSourceUserId())) {
                continue;
            }
            OutboxMessage outboxMessage = new OutboxMessage();
            outboxMessage.setId(sequenceUtils.genOutboxMessageId());
            outboxMessage.setInboxMessageId(inboxMessage.getId());
            outboxMessage.setConversationId(inboxMessage.getConversationId());
            outboxMessage.setSourceUserId(inboxMessage.getSourceUserId());
            outboxMessage.setTargetUserId(chatGroupUser.getUserId());
            outboxMessage.setChatGroupId(inboxMessage.getChatGroupId());
            outboxMessage.setMessageType(inboxMessage.getMessageType());
            outboxMessage.setMessage(inboxMessage.getMessage());
            outboxMessage.setStatus(0);
            outboxMessage.setCreateTime(new Date());
            outboxMessage.setSendTime(inboxMessage.getSendTime());

            outboxMessageList.add(outboxMessage);

            targetUserIdList.add(chatGroupUser.getUserId());
        }
        outboxMessageService.batchAddOutboxMessage(outboxMessageList);

        AppWSMessage appWSMessage = new AppWSMessage();
        appWSMessage.setType(AppWSMessageTypeEnum.NEW_MSG.getTypeName());
        for (Long userId : targetUserIdList) {
            wsConnectionManager.sendMessage(userId, new TextMessage(JSON.toJSONString(appWSMessage)));
        }
    }
}
